# src\services\login.py
from typing import List, Optional, Dict, Any
from src import login_manager, LoginManager
from src import retMes, security, str_utils as stru, orm_curd
from sqlalchemy.orm import Session, Query
from src.models.sys_user import SysUser as sysUserModels
from src.models import sys_menu as SysMenuModels
from sqlalchemy import and_
from src.schemas.sys_user import SysUsers as sysUsersSchemas

from src.schemas.login_manager import AuthManager
from src.schemas.request_model import UpdateModel
from src.schemas import request_model

loginInfo = LoginManager()  # 返回值


def login(db: Session,
          login_data: login_manager.LoginRequest,
          app_manager: Optional[dict] = None):
    username = login_data.username
    password = login_data.password
    # password = stru.get_password_hash(password)

    loginInfo.update_username(username)

    if app_manager:
        app_id = app_manager['app_id']
        api_key = app_manager['api_key']
        api_name = app_manager['api_name']
        language =app_manager['language']
        loginInfo.update_app_id(app_id)
        loginInfo.update_api_key(api_key)
        loginInfo.update_api_name(api_name)

    else:
        message = retMes.Msg(db, -1, '9300',None, ' ').mes()
        return retMes.Error(message=message, data=loginInfo.ret())

    # 获取User信息
    sys_user = (
        db.query(sysUserModels)  # ← 这里传的是类，不是模块
        .filter(sysUserModels.api_id == app_id)
        .filter(sysUserModels.login_id == username)
        .filter(sysUserModels.deletion_mark == 0)
        .first()
    )
    # 2. 空值保护
    if not sys_user:
        message = retMes.Msg(db, app_id, '9222', language).mes()
        return retMes.Error(message=message, data=loginInfo.ret())
    # 3. 转 Pydantic 模型（字段名、类型与 Schema 完全一致）
    user_info = sysUsersSchemas.from_orm(sys_user)
    #是否禁用
    if user_info.effective_date > stru.now_date():
        message = retMes.Msg(db, app_id, '9227', language).mes()
        return retMes.Error(message=message, data=loginInfo.ret())
    if stru.is_not_empty(user_info.expiry_date) and user_info.expiry_date < stru.now_date():
        message = retMes.Msg(db, app_id, '9229', language).mes()
        return retMes.Error(message=message, data=loginInfo.ret())
    if not stru.verify_password(password, user_info.login_password):
        message = retMes.Msg(db, app_id, '9226', language).mes()
        return retMes.Error(message=message, data=loginInfo.ret())

    """
    sys_user = (
    db.query(sysUserModels)
    .filter(
        and_(
            sysUserModels.user_name == username,
            sysUserModels.app_id == app_id
        )
    )
    .first()
)

    """

    loginUser = LoginManager()  # token加密资料
    loginUser.update_api_id(app_id)
    loginUser.update_username(username)
    loginUser.update_user_id(user_info.id)
    loginUser.update_role(user_info.role)
    loginUser.update_email(user_info.email)
    token = security.generate_token(loginUser.loginData())

    loginInfo.update_username(username)
    loginInfo.update_user_name(user_info.user_name)
    loginInfo.update_email(loginUser.loginData()['email'])
    loginInfo.update_role(loginUser.loginData()['role'])
    # loginInfo.update_app_id(app_id)
    # loginInfo.update_api_key(api_key)
    loginInfo.update_token_key(token)
    print(loginInfo)
    return retMes.Success(loginInfo.ret())


def changePassword(db: Session,
                   auth: AuthManager,
                   password_data: login_manager.ChangePasswordRequest
                   ):
    login_id = password_data.login_id
    old_password = password_data.old_password
    new_password = password_data.new_password
    confirm_password = password_data.confirm_password

    return change_password_internal(db,
                                    auth,
                                    "change",
                                    login_id,
                                    new_password,
                                    confirm_password,
                                    old_password)


def refreshPassword(db: Session,
                    auth: AuthManager,
                    password_data: login_manager.RefreshPasswordRequest
                    ):
    """
    刷新用户密码

    :param db:      SQLAlchemy 会话
    :param auth:    登录信息
    :param password_data: 密码数据
    :return:        统一响应格式
    """
    login_id = password_data.login_id
    new_password = password_data.new_password
    confirm_password = password_data.confirm_password
    verification_code = password_data.verification_code
    api_id = auth.api_id
    return change_password_internal(db,
                                    auth,
                                    "refresh",
                                    login_id,
                                    new_password,
                                    confirm_password,
                                    None,
                                    verification_code
                                    )


def change_password_internal(db: Session,
                             auth: AuthManager,
                             operation_mode: str,
                             login_id: str,
                             new_password: str = None,
                             confirm_password: str = None,
                             old_password: str = None,
                             verification_code: str = None):
    """
    修改用户密码

    :param db:      SQLAlchemy 会话
    :param auth:    登录信息
    :param operation_mode:    change/refresh
    :param login_id: 用户 ID
    :param old_password: 变更前密码
    :param new_password: 新密码
    :param confirm_password: 确认新密码
    :param verification_code：验证码，后续备用
    :return:        统一响应格式
    """
    # 验证新密码与确认密码是否一致
    api_id = auth.api_id
    language = auth.language
    if operation_mode == "change" or operation_mode == "refresh" and confirm_password is not None:
        if new_password != confirm_password:
            message = retMes.Msg(db, api_id, '9223', language).mes()
            return retMes.Error(message)
    if operation_mode == "change":
        # 验证新密码与确认密码是否一致
        if new_password == old_password:
            message = retMes.Msg(db, api_id, '9224', language).mes()
            return retMes.Error(message)

    # 获取用户信息
    user = db.query(sysUserModels).filter(
        sysUserModels.api_id == api_id,
        sysUserModels.login_id == login_id
    ).first()
    if not user:
        message = retMes.Msg(db, api_id, '9222', language).mes()
        return retMes.Error(message)

    # 验证变更前密码是否正确
    if operation_mode == "change":
        if not stru.verify_password(old_password, user.login_password):
            message = retMes.Msg(db, api_id, '9225', language).mes()
            return retMes.Error(message)

    # 密码加密处理
    new_password_hash = stru.get_password_hash(new_password)

    # 构造更新模型
    update_model = request_model.UpdateModel([
        request_model.UpdateItem(
            pk_names=["login_id"],
            pk_values=[login_id],
            data={"login_password": new_password_hash}
        )
    ])

    # 调用通用更新接口
    result = orm_curd.update(db,
                             auth,
                             sysUserModels,
                             update_model)

    # 在返回结果中增加变更前后的信息
    print(result)
    print(result["status_code"])
    if result["status_code"] == 200:

        message = retMes.Msg(db, api_id, '9220', language).mes()
        return retMes.Success(None,
                              message,
                              record_count=0).mes()
    else:
        message = result["message"]
        return retMes.Error(message).mes()

    return result

